--[[
-- @Author:	grayson
-- @DateTime: 2020-10-30 23:05:48
-- @Description: 客户端连接服务端使用

--]]


local socket = require("skynet.socket")



--消息打包类
local ClientNet = class("ClientNet")


function ClientNet:ctor()
    self.fd = nil
    self.ip = nil
    self.port = nil
    self.last_package = ""
    self.msg_callbacks = {} --消息回调列表

    self.client_pack = new("client_pack")


    --接收消息
    g.fork(function()
        while true do
            -- print(">>>M:recv_loop>>>")
            if self.fd then
                local str = socket.read(self.fd)
                if str then
                    self:receive(str)
                else
                    g.log:error("接收数据错误,关闭fd:", self.fd)
                    self:close()
                end
            else
                g.sleep(100)
            end
        end
    end)
end

--取大端2个字节
function ClientNet:readShortBig( text ) --big endian
    return text:byte(1)*256 + text:byte(2)
end

--包长度2字节（skynet 规定头2个字节为包长度
function ClientNet:unpackPackage(text)
    local size = #text
    if size < 2 then
        return nil, text
    end
    local pack_size = self:readShortBig(text)
    if size < pack_size + 2 then
        return nil, text
    end
    local offset = 2
    local msg = text:sub(offset + 1, offset + pack_size)
    local last = text:sub(offset + 1 + pack_size)
    return msg, last
end

--连接socket
function ClientNet:connect(ip, port)
    if not ip or not port then
        print("ClientNet:connect ip port is nill___")
        return false
    end
    self.ip = ip
    self.port = port
    self.fd = socket.open(ip, port)
    if not self.fd then
        print("连接 "..ip..":"..port.."失败")
        return false
    end
    print("########连接"..ip..":"..port.."成功#########")
    return true
end

function ClientNet:receive(str)
    -- print("收到数据"..#str)
    self.last_package = self.last_package .. str
    local msg
    while #self.last_package > 0 do
        msg, self.last_package = self:unpackPackage(self.last_package)
        if not msg then
            break
        end
        if msg then
            local _, msg_name, msg_data = self.client_pack:unpack(msg, #msg)
            g.dispatch:dispatchMessage(nil, nil, msg_name, msg_data)
        end
    end
end

function ClientNet:close()
    print("ClientNet:close fd:",self.fd)
    if self.fd then
        socket.close(self.fd)
    end
    self.fd = nil
    os.exit()
end

function ClientNet:send(msg_name, msg_body, conn_type)
    if not self.fd then
        local conn = self:connect(self.ip, self.port)
        if not conn then
            --连接失败            
            return
        end
    end
    self.client_pack:send(self.fd, msg_name, msg_body, conn_type)
end

return ClientNet